package com.xishu.controller;

import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.xishu.annotation.valid.MethodValidator;
import com.xishu.config.Config;
import com.xishu.config.Constant;
import com.xishu.dao.jpa.FoodPandaOrderDao;
import com.xishu.entity.foodPandaOrder.FoodPandaOrder;
import com.xishu.entity.hardware.Printer;
import com.xishu.entity.order.Order;
import com.xishu.entity.shop.FoodPandaConfig;
import com.xishu.entity.shop.Shop;
import com.xishu.service.CommonService;
import com.xishu.service.FoodPandaOrderService;
import com.xishu.service.ShopService;
import com.xishu.service.order.base.OrderService;
import com.xishu.service.order.create.CreateOrderChain;
import com.xishu.service.print.PrinterService;
import com.xishu.service.print.kitchen.KitchenService;
import com.xishu.util.AES;
import com.xishu.util.BeanUtil;
import com.xishu.util.ServletUtil;
import com.xishu.util.Tools;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.List;
import java.util.Map;


@RestController
@Api(description = "foodPanda订单管理")
public class FoodPandaOrderController implements Tools {

    private static final String TOKEN_SECRET = "SnyteunCeerhicJofI";

    private static Logger logger = LoggerFactory.getLogger(FoodPandaOrderController.class);
    private CommonService commonService = CommonService.getInstance();
    private PrinterService printerService = PrinterService.getInstance();
    private OrderService orderService = OrderService.getInstance();
    private KitchenService kitchenService = KitchenService.getInstance();
    private Config config = Config.getInstance();
    private FoodPandaOrderService foodPandaOrderService = FoodPandaOrderService.getInstance();


    @ApiOperation(value = "创建foodPanda订单")
    @PostMapping(value = ("/order/{remoteId}"), produces = ("application/json;charset=UTF-8"))
    @MethodValidator(mustLogin = false, duplicationRequestCheck = true)
    public Map<String, Object> create(@RequestBody FoodPandaOrder foodPandaOrder, @PathVariable String remoteId) throws Exception {
        logger.info("foodPandaOrder is {}", JSONObject.toJSONString(foodPandaOrder));
        Map<String, Object> response = new HashMap<>();

        logger.info("Order start");

        //首先检查是不是重复请求
        FoodPandaOrderDao foodPandaOrderDao = BeanUtil.getBean(FoodPandaOrderDao.class);
        Integer exist = foodPandaOrderDao.isexist(foodPandaOrder.getCode());
        if (exist != null) {
            logger.info("uniquecheck the order");
            response.put("status", "400");
            response.put("reason", "repeat request");
            response.put("message", "same request ...");
            return response;
        }

        logger.info("will create foodPandaOrder");

        logger.info("check the token");
        //获取请求头中的Token
        String authorization = ServletUtil.getRequest().getHeader("authorization");
        String token = authorization.split(" ")[1];
        JWT jwt = JWTUtil.parseToken(token);

        //token校验，第一步，先用secret校验token
        try {
            Algorithm algorithm = Algorithm.HMAC512(getJWTToken(Long.valueOf(remoteId)));
            JWTVerifier build = com.auth0.jwt.JWT.require(algorithm).build();
            build.verify(token);
            logger.info("token verified by the secret passed");
        } catch (Exception e) {
            logger.error("token verified by the secret failed", e);
            response.put("status", "400");
            response.put("reason", "token is not true");
            response.put("message", "Failed to persist ...");
            return response;
        }
        //第二步，再检查token的荷载中是否包含 service： middleware
        Object service = jwt.getPayload("service");
        if (!("middleware").equals(service)) {
            logger.info("validation fails");
            //不合法就劝返
            response.put("status", "400");
            response.put("reason", "validation fails");
            response.put("message", "Failed to persist ...");
            return response;
        }

        logger.info("validation passed");

        //香港测试环境用
        if (config.foodPandaToFixShop()) {
            foodPandaOrder.setRemoteId(String.valueOf(config.foodPandaToFixShopId()));
        } else {
            foodPandaOrder.setRemoteId(remoteId);
        }

        //保存foodpanda原订单
        commonService.createObject(foodPandaOrder);

        Order order = foodPandaOrderService.change(foodPandaOrder);

        Order newOrder = new CreateOrderChain().createOrder(order);

        newOrder.setStatus(Constant.ORDER_STATUS_END);

        List<Long> orderItemIdList = orderService.toOrderItemIdList(newOrder.getOrderItemDetailList());
        //发送至厨房并打印打包单
        printerService.printerOrderItemList(newOrder, orderItemIdList);

        //查找C端结账后客票打印机
        Printer printer1 = new Printer();
        printer1.setShopId(newOrder.getShopId());
        printer1.setPrintPayedOrder(true);
        printer1.setLocation(Constant.PRINTER_LOCATION_BAR_COUNTER);
        Printer barCounterPrinter = commonService.searchOne(printer1);

        //打印小票
        printerService.printOrder(newOrder, barCounterPrinter.getId(), false, false);


        response.put("status", "200");

        Map<String, String> remoteResponse = new HashMap<>();

        remoteResponse.put("remoteOrderId", "POS_RESTAURANT_0001_ORDER_000001");

        response.put("remoteResponse", remoteResponse);

        logger.info("enjoy your meal");

        return response;


    }

    /**
     * 获取JWT配置
     *
     * @param shopId
     * @return
     */
    private String getJWTToken(Long shopId) {
        try {
            Shop shop = ShopService.getInstance().findShopById(shopId);
            FoodPandaConfig foodPandaConfig = shop.getFoodPandaConfig();

            if (!getBoolean(foodPandaConfig.getConfigComplete())) {
                logger.info("not config yet");
                return TOKEN_SECRET;
            }

            if (isEmpty(foodPandaConfig.getTokenSecret())) {
                return TOKEN_SECRET;
            }

            return AES.decrypt(foodPandaConfig.getTokenSecret());
        } catch (Exception e) {
            //为了测试使用
            return TOKEN_SECRET;
        }
    }
}
